package com.kwan.xframe.api;

import java.io.IOException;

import androidx.annotation.NonNull;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;

/**
 * 上传进度
 * Decorates an OkHttp request body to count the number of bytes written when writing it. Can
 * decorate any request body, but is most useful for tracking the upload progress of large
 * multipart requests.
 *
 * @author Leo Nikkil盲
 */
public class CountingRequestBody extends RequestBody {

	protected RequestBody delegate;
	protected Listener listener;
	protected CountingSink countingSink;

	public CountingRequestBody(RequestBody delegate, Listener listener) {
		this.delegate = delegate;
		this.listener = listener;
	}

	@Override
	public MediaType contentType() {
		return delegate.contentType();
	}

	@Override
	public long contentLength() {
		try {
			return delegate.contentLength();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return -1;
	}

	@Override
	public void writeTo(@NonNull BufferedSink sink) throws IOException {
		if (sink instanceof Buffer)
			return;
		BufferedSink bufferedSink;
		countingSink = new CountingSink(sink);
		bufferedSink = Okio.buffer(countingSink);
		delegate.writeTo(bufferedSink);
		bufferedSink.flush();
	}

	protected final class CountingSink extends ForwardingSink {

		private long bytesWritten = 0;

		public CountingSink(Sink delegate) {
			super(delegate);
		}

		@Override
		public void write(Buffer source, long byteCount) throws IOException {
			super.write(source, byteCount);
			bytesWritten += byteCount;
			long contentLength = contentLength();
			double percent = ((double) bytesWritten / (double) contentLength) * 100;
			listener.onRequestProgress(bytesWritten, contentLength, (int) percent);
		}

	}

	public interface Listener {
		void onRequestProgress(long bytesWritten, long contentLength, int percent);
	}

}
